Define a new sched_op hypercall called sched_op_new, which differs from the
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 14 Mar 2006 18:33:45 +0000 (19:33 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 14 Mar 2006 18:33:45 +0000 (19:33 +0100)
legacy hypercall in that it takes a pointer to a block of extra arguments
rather than an opaque unsigned long. The old hypercall still exists, for
backwards compatibility.

The new hypercall supports new sub-command SCHEDOP_poll, which can be used to
wait on a set of event-channel ports with an optional timeout. This is exported
in XenLinux as HYPERVISOR_poll, and used in the pcifront driver to wait on a
response from the pciback driver.

Can also be used for debuggers. :-)

Signed-off-by: Keir Fraser <keir@xensource.com>
Signed-off-by: John Levon <john.levon@sun.com>
16 files changed:
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h
linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h
xen/arch/x86/x86_32/entry.S
xen/arch/x86/x86_64/entry.S
xen/common/event_channel.c
xen/common/schedule.c
xen/include/public/event_channel.h
xen/include/public/sched.h
xen/include/public/xen.h
xen/include/xen/event.h
xen/include/xen/sched.h

index 9d0054980e71dd46efa8b6933d48d942f7101c20..809a63393263794a0d8dd6e0c430a6357b22dd64 100644 (file)
@@ -949,7 +949,7 @@ void __init time_init(void)
 }
 
 /* Convert jiffies to system time. */
-static inline u64 jiffies_to_st(unsigned long j)
+u64 jiffies_to_st(unsigned long j)
 {
        unsigned long seq;
        long delta;
@@ -967,6 +967,7 @@ static inline u64 jiffies_to_st(unsigned long j)
 
        return st;
 }
+EXPORT_SYMBOL(jiffies_to_st);
 
 /*
  * stop_hz_timer / start_hz_timer - enter/exit 'tickless mode' on an idle cpu
index 96791929ee314203b6902fccc33543915b591804..501736ff5a57a3e1dbfa6611fe3c56344c8a94b5 100644 (file)
@@ -40,9 +40,8 @@ static int do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
 {
        int err = 0;
        struct xen_pci_op *active_op = &pdev->sh_info->op;
-       unsigned long irq_flags;
-
-       unsigned int volatile ttl = (1U << 29);
+       unsigned long irq_flags, poll_end;
+       evtchn_port_t port = pdev->evtchn;
 
        spin_lock_irqsave(&pdev->sh_info_lock, irq_flags);
 
@@ -51,14 +50,17 @@ static int do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
        /* Go */
        wmb();
        set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
-       notify_remote_via_evtchn(pdev->evtchn);
-
-       /* IRQs are disabled for the pci config. space reads/writes,
-        * which means no event channel to notify us that the backend
-        * is done so spin while waiting for the answer */
-       while (test_bit
-              (_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)) {
-               if (!ttl) {
+       notify_remote_via_evtchn(port);
+
+       poll_end = jiffies + 5*HZ;
+       clear_evtchn(port);
+
+       while (test_bit(_XEN_PCIF_active,
+                       (unsigned long *)&pdev->sh_info->flags)) {
+               if (HYPERVISOR_poll(&port, 1, poll_end))
+                       BUG();
+               clear_evtchn(port);
+               if (time_after(jiffies, poll_end)) {
                        dev_err(&pdev->xdev->dev,
                                "pciback not responding!!!\n");
                        clear_bit(_XEN_PCIF_active,
@@ -66,7 +68,6 @@ static int do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
                        err = XEN_PCI_ERR_dev_not_found;
                        goto out;
                }
-               ttl--;
        }
 
        memcpy(op, active_op, sizeof(struct xen_pci_op));
index e9ef2d2707b287b9f3e1d7fadc9fffee2cf671ff..a0e63d3ac1dc38f42d3a2925a52fe8f25b367455 100644 (file)
@@ -33,6 +33,7 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
 #include <xen/interface/nmi.h>
+#include <linux/errno.h>
 
 #define __STR(x) #x
 #define STR(x) __STR(x)
@@ -169,6 +170,31 @@ HYPERVISOR_sched_op(
        return _hypercall2(int, sched_op, cmd, arg);
 }
 
+static inline int
+HYPERVISOR_sched_op_new(
+       int cmd, void *arg)
+{
+       return _hypercall2(int, sched_op_new, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_poll(
+       evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
+{
+       struct sched_poll sched_poll = {
+               .ports = ports,
+               .nr_ports = nr_ports,
+               .timeout = jiffies_to_st(timeout)
+       };
+
+       int rc = HYPERVISOR_sched_op_new(SCHEDOP_poll, &sched_poll);
+
+       if (rc == -ENOSYS)
+               rc = HYPERVISOR_sched_op(SCHEDOP_yield, 0);
+
+       return rc;
+}
+
 static inline long
 HYPERVISOR_set_timer_op(
        u64 timeout)
index a6b10e4b2c3c7127a22cd7317a578ecb74c1b2e1..fd5871663233a0869a570434396ed074177eb5b1 100644 (file)
@@ -97,6 +97,9 @@ int xen_create_contiguous_region(
 void xen_destroy_contiguous_region(
     unsigned long vstart, unsigned int order);
 
+/* Turn jiffies into Xen system time. */
+u64 jiffies_to_st(unsigned long jiffies);
+
 #include <asm/hypercall.h>
 
 #if defined(CONFIG_X86_64)
index fd57868dc7e30d4f2ef951c7ce85472d8615eb1c..a77a4166a2ff9bc664c91d0b00953c4fbe37a775 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
+#include <linux/errno.h>
 
 /* FIXME: temp place to hold these page related macros */
 #include <asm/page.h>
@@ -165,6 +166,31 @@ HYPERVISOR_sched_op(
        return _hypercall2(int, sched_op, cmd, arg);
 }
 
+static inline int
+HYPERVISOR_sched_op_new(
+       int cmd, void *arg)
+{
+       return _hypercall2(int, sched_op_new, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_poll(
+       evtchn_port_t *ports, unsigned int nr_ports, unsigned long timeout)
+{
+       struct sched_poll sched_poll = {
+               .ports = ports,
+               .nr_ports = nr_ports,
+               .timeout = jiffies_to_st(timeout)
+       };
+
+       int rc = HYPERVISOR_sched_op_new(SCHEDOP_poll, &sched_poll);
+
+       if (rc == -ENOSYS)
+               rc = HYPERVISOR_sched_op(SCHEDOP_yield, 0);
+
+       return rc;
+}
+
 static inline long
 HYPERVISOR_set_timer_op(
     u64 timeout)
index 4771111e0d58e32ade99e844983cf150986f852c..ab3a64c106654b9795149e1058e5f64aa3d2fb3e 100644 (file)
@@ -44,6 +44,9 @@ extern start_info_t *xen_start_info;
 
 void force_evtchn_callback(void);
 
+/* Turn jiffies into Xen system time. XXX Implement me. */
+#define jiffies_to_st(j)       0
+
 #include <asm/hypercall.h>
 
 // for drivers/xen/privcmd/privcmd.c
index a09a3c879e501665d401a165e141413f1caf5681..57e5568c51a6bf64da8eecf379597d45d9c88268 100644 (file)
@@ -37,6 +37,7 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
 #include <xen/interface/nmi.h>
+#include <linux/errno.h>
 
 #define __STR(x) #x
 #define STR(x) __STR(x)
@@ -174,6 +175,31 @@ HYPERVISOR_sched_op(
        return _hypercall2(int, sched_op, cmd, arg);
 }
 
+static inline int
+HYPERVISOR_sched_op_new(
+       int cmd, void *arg)
+{
+       return _hypercall2(int, sched_op_new, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_poll(
+       evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
+{
+       struct sched_poll sched_poll = {
+               .ports = ports,
+               .nr_ports = nr_ports,
+               .timeout = jiffies_to_st(timeout)
+       };
+
+       int rc = HYPERVISOR_sched_op_new(SCHEDOP_poll, &sched_poll);
+
+       if (rc == -ENOSYS)
+               rc = HYPERVISOR_sched_op(SCHEDOP_yield, 0);
+
+       return rc;
+}
+
 static inline long
 HYPERVISOR_set_timer_op(
        u64 timeout)
index 6e888f1e9cb094d781801059bd6eb00f3517cc97..86c609ce07e027ee23bb08c5c048a190d4f98d40 100644 (file)
@@ -586,6 +586,13 @@ do_arch_sched_op:
         movl %eax,UREGS_eax(%ecx)
         jmp  do_sched_op
 
+do_arch_sched_op_new:
+        # Ensure we return success even if we return via schedule_tail()
+        xorl %eax,%eax
+        GET_GUEST_REGS(%ecx)
+        movl %eax,UREGS_eax(%ecx)
+        jmp  do_sched_op_new
+
 .data
 
 ENTRY(exception_table)
@@ -640,6 +647,7 @@ ENTRY(hypercall_table)
         .long do_mmuext_op
         .long do_acm_op
         .long do_nmi_op
+        .long do_arch_sched_op_new
         .rept NR_hypercalls-((.-hypercall_table)/4)
         .long do_ni_hypercall
         .endr
@@ -674,6 +682,7 @@ ENTRY(hypercall_args_table)
         .byte 4 /* do_mmuext_op         */
         .byte 1 /* do_acm_op            */
         .byte 2 /* do_nmi_op            */
+        .byte 2 /* do_arch_sched_op_new */
         .rept NR_hypercalls-(.-hypercall_args_table)
         .byte 0 /* do_ni_hypercall      */
         .endr
index 984d9d82a5742539ce5380bdf1d1ff1330f162e3..c5249e1d794f5c83332777a61cc716f1e207cb18 100644 (file)
@@ -495,6 +495,13 @@ do_arch_sched_op:
         movq  %rax,UREGS_rax(%r10)
         jmp   do_sched_op
 
+do_arch_sched_op_new:
+        # Ensure we return success even if we return via schedule_tail()
+        xorl  %eax,%eax
+        GET_GUEST_REGS(%r10)
+        movq  %rax,UREGS_rax(%r10)
+        jmp   do_sched_op_new
+
 .data
 
 ENTRY(exception_table)
@@ -549,6 +556,7 @@ ENTRY(hypercall_table)
         .quad do_mmuext_op
         .quad do_acm_op
         .quad do_nmi_op
+        .quad do_arch_sched_op_new
         .rept NR_hypercalls-((.-hypercall_table)/8)
         .quad do_ni_hypercall
         .endr
@@ -583,6 +591,7 @@ ENTRY(hypercall_args_table)
         .byte 4 /* do_mmuext_op         */
         .byte 1 /* do_acm_op            */
         .byte 2 /* do_nmi_op            */
+        .byte 2 /* do_arch_sched_op_new */
         .rept NR_hypercalls-(.-hypercall_args_table)
         .byte 0 /* do_ni_hypercall      */
         .endr
index 97a7d25fe206f9303366206a8f511d806febb21a..b37a6f183a53b8d7408195b0098b592798b90e29 100644 (file)
@@ -438,6 +438,47 @@ long evtchn_send(unsigned int lport)
     return ret;
 }
 
+void evtchn_set_pending(struct vcpu *v, int port)
+{
+    struct domain *d = v->domain;
+    shared_info_t *s = d->shared_info;
+
+    /*
+     * The following bit operations must happen in strict order.
+     * NB. On x86, the atomic bit operations also act as memory barriers.
+     * There is therefore sufficiently strict ordering for this architecture --
+     * others may require explicit memory barriers.
+     */
+
+    if ( test_and_set_bit(port, &s->evtchn_pending[0]) )
+        return;
+
+    if ( !test_bit        (port, &s->evtchn_mask[0])    &&
+         !test_and_set_bit(port / BITS_PER_LONG,
+                           &v->vcpu_info->evtchn_pending_sel) &&
+         !test_and_set_bit(0, &v->vcpu_info->evtchn_upcall_pending) )
+    {
+        evtchn_notify(v);
+    }
+    else if ( unlikely(test_bit(_VCPUF_blocked, &v->vcpu_flags) &&
+                       v->vcpu_info->evtchn_upcall_mask) )
+    {
+        /*
+         * Blocked and masked will usually mean that the VCPU executed 
+         * SCHEDOP_poll. Kick the VCPU in case this port is in its poll list.
+         */
+        vcpu_unblock(v);
+    }
+}
+
+void send_guest_virq(struct vcpu *v, int virq)
+{
+    int port = v->virq_to_evtchn[virq];
+
+    if ( likely(port != 0) )
+        evtchn_set_pending(v, port);
+}
+
 void send_guest_pirq(struct domain *d, int pirq)
 {
     int port = d->pirq_to_evtchn[pirq];
index 695966027bd84cf9e5ee22a9509de312b6662ee2..78863e58250d9af0c92fa7485e797214136df72b 100644 (file)
@@ -27,6 +27,7 @@
 #include <xen/softirq.h>
 #include <xen/trace.h>
 #include <xen/mm.h>
+#include <xen/guest_access.h>
 #include <public/sched.h>
 #include <public/sched_ctl.h>
 
@@ -42,6 +43,7 @@ string_param("sched", opt_sched);
 static void s_timer_fn(void *unused);
 static void t_timer_fn(void *unused);
 static void dom_timer_fn(void *data);
+static void poll_timer_fn(void *data);
 
 /* This is global for now so that private implementations can reach it */
 struct schedule_data schedule_data[NR_CPUS];
@@ -164,8 +166,9 @@ struct vcpu *alloc_vcpu(
 
 void sched_add_domain(struct vcpu *v) 
 {
-    /* Initialise the per-domain timer. */
+    /* Initialise the per-domain timers. */
     init_timer(&v->timer, dom_timer_fn, v, v->processor);
+    init_timer(&v->poll_timer, poll_timer_fn, v, v->processor);
 
     if ( is_idle_vcpu(v) )
     {
@@ -181,6 +184,8 @@ void sched_add_domain(struct vcpu *v)
 void sched_rem_domain(struct vcpu *v) 
 {
     kill_timer(&v->timer);
+    kill_timer(&v->poll_timer);
+
     SCHED_OP(rem_task, v);
     TRACE_2D(TRC_SCHED_DOM_REM, v->domain->domain_id, v->vcpu_id);
 }
@@ -270,6 +275,55 @@ static long do_block(void)
     return 0;
 }
 
+static long do_poll(struct sched_poll *sched_poll)
+{
+    struct vcpu  *v = current;
+    evtchn_port_t port;
+    long          rc = 0;
+    unsigned int  i;
+
+    /* Fairly arbitrary limit. */
+    if ( sched_poll->nr_ports > 128 )
+        return -EINVAL;
+
+    if ( !guest_handle_okay(sched_poll->ports, sched_poll->nr_ports) )
+        return -EFAULT;
+
+    /* Ensure that upcalls are disabled: tested by evtchn_set_pending(). */
+    if ( !v->vcpu_info->evtchn_upcall_mask )
+        return -EINVAL;
+
+    set_bit(_VCPUF_blocked, &v->vcpu_flags);
+
+    /* Check for events /after/ blocking: avoids wakeup waiting race. */
+    for ( i = 0; i < sched_poll->nr_ports; i++ )
+    {
+        rc = -EFAULT;
+        if ( __copy_from_guest_offset(&port, sched_poll->ports, i, 1) )
+            goto out;
+
+        rc = -EINVAL;
+        if ( port >= MAX_EVTCHNS )
+            goto out;
+
+        rc = 0;
+        if ( evtchn_pending(v->domain, port) )
+            goto out;
+    }
+
+    if ( sched_poll->timeout != 0 )
+        set_timer(&v->poll_timer, sched_poll->timeout);
+
+    TRACE_2D(TRC_SCHED_BLOCK, v->domain->domain_id, v->vcpu_id);
+    __enter_scheduler();
+
+    stop_timer(&v->poll_timer);
+
+ out:
+    clear_bit(_VCPUF_blocked, &v->vcpu_flags);
+    return rc;
+}
+
 /* Voluntarily yield the processor for this allocation. */
 static long do_yield(void)
 {
@@ -311,6 +365,61 @@ long do_sched_op(int cmd, unsigned long arg)
     return ret;
 }
 
+long do_sched_op_new(int cmd, GUEST_HANDLE(void) arg)
+{
+    long ret = 0;
+
+    switch ( cmd )
+    {
+    case SCHEDOP_yield:
+    {
+        ret = do_yield();
+        break;
+    }
+
+    case SCHEDOP_block:
+    {
+        ret = do_block();
+        break;
+    }
+
+    case SCHEDOP_shutdown:
+    {
+        struct sched_shutdown sched_shutdown;
+
+        ret = -EFAULT;
+        if ( copy_from_guest(&sched_shutdown, arg, 1) )
+            break;
+
+        ret = 0;
+        TRACE_3D(TRC_SCHED_SHUTDOWN,
+                 current->domain->domain_id, current->vcpu_id,
+                 sched_shutdown.reason);
+        domain_shutdown(current->domain, (u8)sched_shutdown.reason);
+
+        break;
+    }
+
+    case SCHEDOP_poll:
+    {
+        struct sched_poll sched_poll;
+
+        ret = -EFAULT;
+        if ( copy_from_guest(&sched_poll, arg, 1) )
+            break;
+
+        ret = do_poll(&sched_poll);
+
+        break;
+    }
+
+    default:
+        ret = -ENOSYS;
+    }
+
+    return ret;
+}
+
 /* Per-domain one-shot-timer hypercall. */
 long do_set_timer_op(s_time_t timeout)
 {
@@ -518,6 +627,13 @@ static void dom_timer_fn(void *data)
     send_guest_virq(v, VIRQ_TIMER);
 }
 
+/* SCHEDOP_poll timeout callback. */
+static void poll_timer_fn(void *data)
+{
+    struct vcpu *v = data;
+    vcpu_unblock(v);
+}
+
 /* Initialise the data structures. */
 void __init scheduler_init(void)
 {
index a1c6235c62e891679a23874d45a2715b5d26f2c3..c5561630341cdc8aca2c8f3cbbaf72ed1b25acf4 100644 (file)
@@ -10,6 +10,7 @@
 #define __XEN_PUBLIC_EVENT_CHANNEL_H__
 
 typedef uint32_t evtchn_port_t;
+DEFINE_GUEST_HANDLE(evtchn_port_t);
 
 /*
  * EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
index a1a03de7ab15533d90e9c55863018bad2acbf30b..364b1697240ac8944001610c90ebe6b84fc3c66c 100644 (file)
@@ -9,16 +9,32 @@
 #ifndef __XEN_PUBLIC_SCHED_H__
 #define __XEN_PUBLIC_SCHED_H__
 
+#include "event_channel.h"
+
 /*
- * Prototype for this hypercall is:
- *  int sched_op(int cmd, unsigned long arg)
+ * There are two forms of this hypercall.
+ * 
+ * The first and preferred version is only available from Xen 3.0.2. 
+ * The prototype for this hypercall is:
+ *  long sched_op_new(int cmd, void *arg)
+ * @cmd == SCHEDOP_??? (scheduler operation).
+ * @arg == Operation-specific extra argument(s), as described below.
+ * 
+ * The legacy version of this hypercall supports only the following commands:
+ * SCHEDOP_yield, SCHEDOP_block, and SCHEDOP_shutdown. The prototype for the
+ * legacy hypercall is:
+ *  long sched_op(int cmd, unsigned long arg)
  * @cmd == SCHEDOP_??? (scheduler operation).
- * @arg == Operation-specific extra argument(s).
+ * @arg == 0               (SCHEDOP_yield and SCHEDOP_block)
+ *      == SHUTDOWN_* code (SCHEDOP_shutdown)
+ * 
+ * The sub-command descriptions below describe extra arguments for the
+ * sched_op_new() hypercall.
  */
 
 /*
  * Voluntarily yield the CPU.
- * @arg == 0.
+ * @arg == NULL.
  */
 #define SCHEDOP_yield       0
 
  * If called with event upcalls masked, this operation will atomically
  * reenable event delivery and check for pending events before blocking the
  * VCPU. This avoids a "wakeup waiting" race.
- * @arg == 0.
+ * @arg == NULL.
  */
 #define SCHEDOP_block       1
 
 /*
  * Halt execution of this domain (all VCPUs) and notify the system controller.
- * @arg == SHUTDOWN_??? (reason for shutdown).
+ * @arg == pointer to sched_shutdown structure.
  */
 #define SCHEDOP_shutdown    2
+typedef struct sched_shutdown {
+    unsigned int reason; /* SHUTDOWN_* */
+} sched_shutdown_t;
+DEFINE_GUEST_HANDLE(sched_shutdown_t);
+
+/*
+ * Poll a set of event-channel ports. Return when one or more are pending. An
+ * optional timeout may be specified.
+ * @arg == pointer to sched_poll structure.
+ */
+#define SCHEDOP_poll        3
+typedef struct sched_poll {
+    GUEST_HANDLE(evtchn_port_t) ports;
+    unsigned int nr_ports;
+    uint64_t timeout;
+} sched_poll_t;
+DEFINE_GUEST_HANDLE(sched_poll_t);
 
 /*
- * Reason codes for SCHEDOP_shutdown. These may be interpreted by controller
+ * Reason codes for SCHEDOP_shutdown. These may be interpreted by control
  * software to determine the appropriate action. For the most part, Xen does
  * not care about the shutdown code.
  */
index 12d3fb4920e245a38a904cc2dc59d61742144d59..5d88c9c8afb463638336524d550a8545146f2592 100644 (file)
@@ -59,6 +59,7 @@
 #define __HYPERVISOR_mmuext_op            26
 #define __HYPERVISOR_acm_op               27
 #define __HYPERVISOR_nmi_op               28
+#define __HYPERVISOR_sched_op_new         29
 
 /* 
  * VIRTUAL INTERRUPTS
index 2e0c2712cc52d17438b2c685fedea46a9b4515d0..8487a25c7bfb2bba6c57145267cdfdacbb50dce5 100644 (file)
 #include <asm/bitops.h>
 #include <asm/event.h>
 
-/*
- * EVENT-CHANNEL NOTIFICATIONS
- * NB. On x86, the atomic bit operations also act as memory barriers. There
- * is therefore sufficiently strict ordering for this architecture -- others
- * may require explicit memory barriers.
- */
-
-static inline void evtchn_set_pending(struct vcpu *v, int port)
-{
-    struct domain *d = v->domain;
-    shared_info_t *s = d->shared_info;
-
-    /* These four operations must happen in strict order. */
-    if ( !test_and_set_bit(port, &s->evtchn_pending[0]) &&
-         !test_bit        (port, &s->evtchn_mask[0])    &&
-         !test_and_set_bit(port / BITS_PER_LONG,
-                           &v->vcpu_info->evtchn_pending_sel) &&
-         !test_and_set_bit(0, &v->vcpu_info->evtchn_upcall_pending) )
-    {
-        evtchn_notify(v);
-    }
-}
+extern void evtchn_set_pending(struct vcpu *v, int port);
 
 /*
  * send_guest_virq:
  *  @v:        VCPU to which virtual IRQ should be sent
  *  @virq:     Virtual IRQ number (VIRQ_*)
  */
-static inline void send_guest_virq(struct vcpu *v, int virq)
-{
-    int port = v->virq_to_evtchn[virq];
-
-    if ( likely(port != 0) )
-        evtchn_set_pending(v, port);
-}
+extern void send_guest_virq(struct vcpu *v, int virq);
 
 /*
  * send_guest_pirq:
@@ -63,6 +36,9 @@ extern void send_guest_pirq(struct domain *d, int pirq);
     (!!(v)->vcpu_info->evtchn_upcall_pending &  \
       !(v)->vcpu_info->evtchn_upcall_mask)
 
+#define evtchn_pending(d, p)                    \
+    (test_bit((p), &(d)->shared_info->evtchn_pending[0]))
+
 /* Send a notification from a local event-channel port. */
 extern long evtchn_send(unsigned int lport);
 
index 3b3e8389ff9bd76a4173a2ee28cb249d8b44b9ad..1a74f74a8211dc69328279a05a1c90dcb62da30b 100644 (file)
@@ -67,6 +67,8 @@ struct vcpu
     struct timer     timer;         /* one-shot timer for timeout values */
     unsigned long    sleep_tick;    /* tick at which this vcpu started sleep */
 
+    struct timer     poll_timer;    /* timeout for SCHEDOP_poll */
+
     void            *sched_priv;    /* scheduler-specific data */
 
     struct vcpu_runstate_info runstate;